﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Interop;
using System.Windows.Forms;
using Bainx.Extend;

namespace Bainx.WPF.Extend.Control
{
    /// <summary>
    /// Interaction logic for WebBrowserUserControl.xaml
    /// </summary>
    public partial class WebBrowserUserControl : System.Windows.Controls.UserControl
    {

        private System.Windows.Forms.WebBrowser webBrowser ;//= new System.Windows.Forms.WebBrowser();
        private FormWebBrowser winForm;
       // private Form winForm;
        private Window owner;
        private TabItem tabItem;

        /// <summary>
        /// 用于可能存在的浏览器关联的tabItem
        /// </summary>
        public TabItem TabItem
        {
            get { return tabItem; }
            set { tabItem = value; }
        }

        /// <summary>
        /// 控件的所有者窗体
        /// </summary>
        public Window Owner
        {
            get { return owner; }
            set { owner = value; }
        }
        private Exception exception = new Exception();

        #region //从System.Windows.Forms.WebBrower实例得到的属性
        /// <summary>
        ///  获取一个 System.Windows.Forms.HtmlDocument，它表示当前显示在 WebBrowser 控件中的网页。
        /// </summary>
        public System.Windows.Forms.HtmlDocument Document
        {
            get { return webBrowser.Document; }
        }
        /// <summary>
        /// 获取或设置一个流，该流包含显示在 WebBrowser 控件中的网页的内容。
        /// </summary>
        public System.IO.Stream DocumentStream
        {
            get { return webBrowser.DocumentStream; }
            set { webBrowser.DocumentStream = value; }
        }
        /// <summary>
        /// 获取或设置显示在 WebBrowser 控件中的页的 HTML 内容。
        /// </summary>
        public string DocumentText
        {
            get { return webBrowser.DocumentText; }
            set { webBrowser.DocumentText = value; }
        }
        /// <summary>
        /// 获取当前显示在 WebBrowser 控件中的文档的标题。
        /// </summary>
        public string DocumentTitle
        {
            get { return webBrowser.DocumentTitle; }
        }
        /// <summary>
        /// 获取当前显示在 WebBrowser 控件中的文档的类型。
        /// </summary>
        public string DocumentType
        {
            get { return webBrowser.DocumentType; }
        }
        /// <summary>
        /// 获取一个值，该值指示导航历史记录中的上一页是否可用，如果可用，WebBrowser.GoBack() 方法才能成功。
        /// </summary>
        public bool CanGoBack
        {
            get { return webBrowser.CanGoBack; }
        }
        /// <summary>
        /// 获取一个值，该值指示导航历史记录中的下一页是否可用，如果可用，System.Windows.Forms.WebBrowser.GoForward()方法才能成功。
        /// </summary>
        public bool CanGoForward
        {
            get { return webBrowser.CanGoForward; }
        }
        /// <summary>
        /// 获取一个值，该值指示 WebBrowser 控件的当前状态。
        /// </summary>
        public System.Windows.Forms.WebBrowserReadyState ReadyState
        {
            get { return webBrowser.ReadyState; }
        }
        /// <summary>
        /// 获取或设置一个值，该值指示 WebBrowser 是否显示对话框，如脚本错误消息。
        /// </summary>
        public bool ScriptErrorsSuppressed
        {
            get { return webBrowser.ScriptErrorsSuppressed; }
            set { webBrowser.ScriptErrorsSuppressed = value; }
        }
        /// <summary>
        /// 获取或设置一个值，该值指示是否在 WebBrowser 控件中显示滚动条。
        /// </summary>
        public bool ScrollBarsEnabled
        {
            get { return webBrowser.ScrollBarsEnabled; }
            set { webBrowser.ScrollBarsEnabled = value; }
        }
        /// <summary>
        /// 获取 WebBrowser 控件的状态文本。
        /// </summary>
        public string StatusText
        {
            get { return webBrowser.StatusText; }
        }
        /// <summary>
        /// 获取或设置一个值，该值指示 WebBrowser 控件中是否启用了键盘快捷键。
        /// </summary>
        public bool WebBrowserShortcutsEnabled
        {
            get { return webBrowser.WebBrowserShortcutsEnabled; }
            set { webBrowser.WebBrowserShortcutsEnabled = value; }
        }
        /// <summary>
        /// 获取或设置一个值，该值指示 WebBrowser 控件是否导航到拖放到它上面的文档。
        /// </summary>
        public bool AllowWebBrowserDrop
        {
            get { return webBrowser.AllowWebBrowserDrop; }
            set { webBrowser.AllowWebBrowserDrop = value; }
        }
        /// <summary>
        /// 获取或设置一个值，该值指示控件在加载其初始页之后是否可以导航到其他页。
        /// </summary>
        public bool AllowNavigation
        {
            get { return webBrowser.AllowNavigation; }
            set { webBrowser.AllowNavigation = value; }
        }
        /// <summary>
        /// 获取或设置一个值，该值指示 WebBrowser 控件是否启用了快捷菜单。
        /// </summary>
        public bool IsWebBrowserContextMenuEnabled
        {
            get { return webBrowser.IsWebBrowserContextMenuEnabled; }
            set { webBrowser.IsWebBrowserContextMenuEnabled = value; }
        }


        #endregion //从System.Windows.Forms.WebBrower实例得到的属性

        #region //从System.Windows.Forms.WebBrower实例得到的事件
        public event EventHandler CanGoBackChanged
        {
            add { webBrowser.CanGoBackChanged += value; }
            remove { webBrowser.CanGoBackChanged -= value; }
        }
        public event EventHandler CanGoForwardChanged
        {
            add { webBrowser.CanGoForwardChanged += value; }
            remove { webBrowser.CanGoForwardChanged -= value; }
        }
        public event EventHandler CausesValidationChanged
        {
            add { webBrowser.CausesValidationChanged += value; }
            remove { webBrowser.CausesValidationChanged -= value; }
        }
        public event EventHandler ClientSizeChanged
        {
            add { webBrowser.ClientSizeChanged += value; }
            remove { webBrowser.ClientSizeChanged -= value; }
        }
        public event EventHandler ContextMenuChanged
        {
            add { webBrowser.ContextMenuChanged += value; }
            remove { webBrowser.ContextMenuChanged -= value; }
        }
        public event EventHandler ContextMenuStripChanged
        {
            add { webBrowser.ContextMenuStripChanged += value; }
            remove { webBrowser.ContextMenuStripChanged -= value; }
        }
        public event ControlEventHandler ControlAdded
        {
            add { webBrowser.ControlAdded += value; }
            remove { webBrowser.ControlAdded -= value; }
        }
        public event ControlEventHandler ControlRemoved
        {
            add { webBrowser.ControlRemoved += value; }
            remove { webBrowser.ControlRemoved -= value; }
        }
        public event EventHandler Disposed
        {
            add { webBrowser.Disposed += value; }
            remove { webBrowser.Disposed -= value; }
        }
        public event WebBrowserDocumentCompletedEventHandler DocumentCompleted
        {
            add { webBrowser.DocumentCompleted += value; }
            remove { webBrowser.DocumentCompleted -= value; }
        }
        public event EventHandler DocumentTitleChanged;
        //{
        //    add { webBrowser.DocumentTitleChanged += value; }
        //    remove { webBrowser.DocumentTitleChanged -= value; }
        //}
        public event EventHandler EncryptionLevelChanged
        {
            add { webBrowser.EncryptionLevelChanged += value; }
            remove { webBrowser.EncryptionLevelChanged -= value; }
        }
        public event EventHandler FileDownload
        {
            add { webBrowser.FileDownload += value; }
            remove { webBrowser.FileDownload -= value; }
        }
        public event EventHandler BGotFocus
        {
            add { webBrowser.GotFocus += value; }
            remove { webBrowser.GotFocus -= value; }
        }
        public event EventHandler HandleCreated
        {
            add { webBrowser.HandleCreated += value; }
            remove { webBrowser.HandleCreated -= value; }
        }
        public event EventHandler HandleDestroyed
        {
            add { webBrowser.HandleDestroyed += value; }
            remove { webBrowser.HandleDestroyed -= value; }
        }
        public event InvalidateEventHandler Invalidated
        {
            add { webBrowser.Invalidated += value; }
            remove { webBrowser.Invalidated -= value; }
        }
        public event EventHandler LocationChanged
        {
            add { webBrowser.LocationChanged += value; }
            remove { webBrowser.LocationChanged -= value; }
        }
        public event EventHandler BLostFocus
        {
            add { webBrowser.LostFocus += value; }
            remove { webBrowser.LostFocus -= value; }
        }
        public event EventHandler MarginChanged
        {
            add { webBrowser.MarginChanged += value; }
            remove { webBrowser.MarginChanged -= value; }
        }
        public event EventHandler Move
        {
            add { webBrowser.Move += value; }
            remove { webBrowser.Move -= value; }
        }
        public event WebBrowserNavigatedEventHandler Navigated
        {
            add { webBrowser.Navigated += value; }
            remove { webBrowser.Navigated -= value; }
        }
        public event WebBrowserNavigatingEventHandler Navigating
        {
            add { webBrowser.Navigating += value; }
            remove { webBrowser.Navigating -= value; }
        }
        public event CancelEventHandler NewWindow
        {
            add { webBrowser.NewWindow += value; }
            remove { webBrowser.NewWindow -= value; }
        }
        public event EventHandler ParentChanged
        {
            add { webBrowser.ParentChanged += value; }
            remove { webBrowser.ParentChanged -= value; }
        }
        public event PreviewKeyDownEventHandler BPreviewKeyDown
        {
            add { webBrowser.PreviewKeyDown += value; }
            remove { webBrowser.PreviewKeyDown -= value; }
        }
        public event WebBrowserProgressChangedEventHandler ProgressChanged
        {
            add { webBrowser.ProgressChanged += value; }
            remove { webBrowser.ProgressChanged -= value; }
        }
        public event EventHandler RegionChanged
        {
            add { webBrowser.RegionChanged += value; }
            remove { webBrowser.RegionChanged -= value; }
        }
        public event EventHandler Resize
        {
            add { webBrowser.Resize += value; }
            remove { webBrowser.Resize -= value; }
        }
        public event EventHandler BSizeChanged
        {
            add { webBrowser.SizeChanged += value; }
            remove { webBrowser.SizeChanged -= value; }
        }
        public event EventHandler StatusTextChanged
        {
            add { webBrowser.StatusTextChanged += value; }
            remove { webBrowser.StatusTextChanged -= value; }
        }
        public event EventHandler SystemColorsChanged
        {
            add { webBrowser.SystemColorsChanged += value; }
            remove { webBrowser.SystemColorsChanged -= value; }
        }
        public event EventHandler TabIndexChanged
        {
            add { webBrowser.TabIndexChanged += value; }
            remove { webBrowser.TabIndexChanged -= value; }
        }
        public event EventHandler TabStopChanged
        {
            add { webBrowser.TabStopChanged += value; }
            remove { webBrowser.TabStopChanged -= value; }
        }
        public event EventHandler Validated
        {
            add { webBrowser.Validated += value; }
            remove { webBrowser.Validated -= value; }
        }
        public event CancelEventHandler Validating
        {
            add { webBrowser.Validating += value; }
            remove { webBrowser.Validating -= value; }
        }
        public event EventHandler VisibleChanged
        {
            add { webBrowser.VisibleChanged += value; }
            remove { webBrowser.VisibleChanged -= value; }
        }
        #endregion webBrowser 事件


        public WebBrowserUserControl()
        {  
            InitializeComponent();

            dpVisibility.AddValueChanged(this, OnVisibilityChanged);

            this.Visibility = System.Windows.Visibility.Hidden;

            webBrowser = winForm.WebBrowser;
            //webBrowser.AllowWebBrowserDrop = false;
            webBrowser.ScriptErrorsSuppressed = true;
            webBrowser.IsWebBrowserContextMenuEnabled = false;
            webBrowser.WebBrowserShortcutsEnabled = false;
           // webBrowser.Visible = true;
            //webBrowser.
           
            webBrowser.ScrollBarsEnabled = false;
           // webBrowser.NewWindow+=new CancelEventHandler(webBrowser_NewWindow);
            webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
            webBrowser.DocumentTitleChanged += new EventHandler(webBrowser_DocumentTitleChanged);
            
           // this.Visibility = System.Windows.Visibility.Hidden;
                        
        }

        private bool openNewWindowForSelf = false;
        public bool OpenNewWindowForSelf
        {
            get { return openNewWindowForSelf; }
            set 
            {
                if (value)
                    webBrowser.NewWindow += new CancelEventHandler(webBrowser_NewWindow);
                else
                    webBrowser.NewWindow -= new CancelEventHandler(webBrowser_NewWindow);
            }
        }
        

        void webBrowser_DocumentTitleChanged(object sender, EventArgs e)
        {
            if (DocumentTitleChanged != null) DocumentTitleChanged(this, e);
        }
        public WebBrowserUserControl(Window Owner)
            : this()
        {
            owner = Owner;
        }

        void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            webBrowser.ScrollBarsEnabled = webBrowser.Document.Body.ClientRectangle.Height > webBrowser.Height;
        }

        /// <summary>
        /// 如果导航历史记录中的上一页可用，则将 System.Windows.Forms.WebBrowser 控件导航到该页。
        /// </summary>
        /// <returns>如果导航成功，则为 true；如果导航历史记录中的上一页不可用，则为 false。</returns>
        public bool GoBack()
        {
            return webBrowser.GoBack();            
        }
        /// <summary>
        /// 如果导航历史记录中的下一页可用，则将 System.Windows.Forms.WebBrowser 控件导航到该页。
        /// </summary>
        /// <returns>如果导航成功，则为 true；如果导航历史记录中的下一页不可用，则为 false。</returns>
        public bool GoForward()
        {
            return webBrowser.GoForward();
        }
        /// <summary>
        /// 将 WebBrowser 控件导航到当前用户的主页。
        /// </summary>
        public void GoHome()
        {
            webBrowser.GoHome();            
        }
        /// <summary>
        /// 通过检查服务器获取更新版本，重新加载当前显示在 WebBrowser 控件中的文档。
        /// </summary>
        public void Refresh()
        {
            webBrowser.Refresh();
        }
        /// <summary>
        /// 使用指定的刷新选项重新加载当前显示在 WebBrowser 控件中的文档。
        /// </summary>
        /// <param name="opt">System.Windows.Forms.WebBrowserRefreshOption 值之一。</param>
        public void Refresh(WebBrowserRefreshOption opt)
        {
            webBrowser.Refresh(opt);
        }

        /// <summary>
        /// 实现在新窗口打开新的URL时，改为在本窗口打开。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void webBrowser_NewWindow(object sender, CancelEventArgs e)
        {
            System.Windows.Forms.WebBrowser webBrowser_temp = (System.Windows.Forms.WebBrowser)sender;
            string newUrl = webBrowser_temp.Document.ActiveElement.GetAttribute("href");
            webBrowser.Url = new Uri(newUrl);
            e.Cancel = true;
        }

        
       


        //private int htmlScrollHeight = -1;
        //public int HtmlScrollHeight
        //{
        //    get
        //    {
        //        if (htmlScrollHeight != -1)
        //        {
        //            return htmlScrollHeight;
        //        }
        //        else
        //        {
        //            try
        //            {
        //                htmlScrollHeight = (int)(webBrowser.Document.Body.ScrollRectangle.Bottom - PageHeight);
        //            }
        //            catch (System.Exception ex)
        //            {

        //            }

        //            return htmlScrollHeight;
        //        }
        //    }
        //}


        public static readonly DependencyPropertyDescriptor dpVisibility = DependencyPropertyDescriptor.FromProperty(VisibilityProperty, typeof(WebBrowserUserControl));


        public Uri Uri
        {
            set
            {
                SetValue(UriProperty, value);
            }
            get
            {
                return (Uri)GetValue(UriProperty);
            }
        }

        public static readonly DependencyProperty UriProperty = DependencyProperty.Register("Uri", typeof(Uri),
                                                                typeof(WebBrowserUserControl),
                                                                new FrameworkPropertyMetadata(null, OnUriPropertyChanged));

        
        private static void OnUriPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {            
            WebBrowserUserControl myUserControl = obj as WebBrowserUserControl;
            if (myUserControl != null)
            {
                try
                {
                    Uri uritemp = e.NewValue as Uri;
                    myUserControl.webBrowser.Url = uritemp;
                }
                catch { }
            }
            
        }  
      
        private void OnVisibilityChanged(object sender, EventArgs e)
        {
            SetFormParam();

            if (this.Visibility == Visibility.Visible && owner != null)
            {
                // InitialShow();

                Reposition();
                Win WinHandle = new Win(((HwndSource)HwndSource.FromVisual(owner)).Handle);
                //Win WinHandle = new Win((new System.Windows.Forms.Form()).Handle);
                winForm.Show(WinHandle);
                

            }
            else
            //if (this.Visibility == Visibility.Hidden)
            {
                winForm.Visible = false;
            }
            //else
            //{
            //    //winForm.Visible = true;
            //}
        }     

       

        private void SetFormParam()
        {
            if (winForm == null)
            {
                winForm = new FormWebBrowser();
                
                
               // winForm = new Form();
               // winForm.
                //winForm.Visible = false;
                //winForm.ShowInTaskbar = false;
                //winForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                
                //webBrowser.ScrollBarsEnabled = true;
               // webBrowser.Dock = System.Windows.Forms.DockStyle.Fill;
               // winForm.Controls.Add(webBrowser);               
                //owner = App.Current.MainWindow;
            }
        }

        private void InitialShow()
        {
            ////set start location
            //Point offset = this.TranslatePoint(new Point(0, 0), owner);
            //HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(owner);
            //CompositionTarget ct = hwndSource.CompositionTarget;
            //offset = ct.TransformToDevice.Transform(offset);
            //Win32.POINT screenLocation = new Win32.POINT(offset);
        }

        public void Reposition()
        { 
            Reposition(owner);           
        }
        public void Reposition(Window owner)
        { 
            Point size = new Point(this.ActualWidth, this.ActualHeight);
            Reposition(owner, size);
        }
        public void Reposition(Window Owner, Point size)
        {
            if (winForm != null)
            {
                owner = Owner;
                Point offset = this.TranslatePoint(new Point(0, 0), Owner);
                //Point size = new Point(this.ActualWidth, this.ActualHeight);
                HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(Owner);
                CompositionTarget ct = hwndSource.CompositionTarget;
                offset = ct.TransformToDevice.Transform(offset);
                size = ct.TransformToDevice.Transform(size);

                Win32.POINT screenLocation = new Win32.POINT(offset);
                Win32.ClientToScreen(hwndSource.Handle, ref screenLocation);
                Win32.POINT screenSize = new Win32.POINT(size);

                Win32.MoveWindow(winForm.Handle, screenLocation.X, screenLocation.Y, screenSize.X, screenSize.Y, true);
               
                //winForm.Visible = true ;
            }
        }

        public ImageBrush FormToBackgroundBrush()
        {
            System.Drawing.Bitmap bitmap = FormWebBrowser.PrintSystemScreen(this.winForm);
            BitmapImage bi = new BitmapImage();
            System.IO.MemoryStream ms = new System.IO.MemoryStream();           
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);            
            bi.BeginInit();
            bi.StreamSource = ms;
            bi.EndInit();
            this.winForm.Visible = false;
            return new ImageBrush(bi);
        }
        public void RepositionEnd()
        {
            this.winForm.Visible = true;
        }

        private void DisposeForm()
        {
            try
            {
                webBrowser.Dispose();
                winForm.Dispose();
            }
            catch { }
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {            
            SetFormParam();
        }

        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            try
            {
                webBrowser.Dispose();
                winForm.Dispose();

            }
            catch { }
        }

      
       


    }

    class Win : System.Windows.Forms.IWin32Window
    {
        public Win(IntPtr Handle)
        {
            handle = Handle;
        }
        IntPtr handle;
        public IntPtr Handle
        {
            get { return this.handle; }
        }
        public  CreateParams CreateParams
        {
            get
            {
                CreateParams cp = new System.Windows.Forms.CreateParams();
                cp.ClassStyle = 0x8;
                cp.ExStyle = 0x50000;
                cp.Style = 0x2CF0000;
                return cp;
            }
        }
    }

    
}
